﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AzukiMap.Layer;
using System.Collections.Generic;
using AzukiMap.Renderer;
using AzukiMap.MapSource;

namespace AzukiMapUI
{
	public partial class StyleSelect : UserControl
	{
        DialogOpener _dialogOpener;
        IVectorStyle _style;
        //MapSourceTypes _layerType;
        VectorSourceTypes _vectorType;

        bool _inited = false;
        const double GRID_HEIGHT = 26;

        /*
        public MapSourceTypes LayerType
        {
            set { 
                SetRowVisibility(value);
                _layerType = value;
            }
        }
         */

        public VectorSourceTypes VectorType
        {
            get { return _vectorType; }
            set {
                SetRowVisibility(value);
                _vectorType = value; 
            }
        }

        public IVectorStyle Style
        {
            get { return _style; }
            set { 
                _style = value;
                SetForm();
            }
        }

		public StyleSelect()
		{
			// Required to initialize variables
			InitializeComponent();
            _dialogOpener = new DialogOpener();
            _inited = true;

            MinimizeAllRows();
		}

        void SetForm()
        {
            TbPointWidth.Text = _style.PointWidth.ToString();
            TbPointHeight.Text = _style.PointHeight.ToString();
            TbPointCenterX.Text = _style.AdjustX.ToString();
            TbPointCenterY.Text = _style.AdjustY.ToString();
            TbStrokeOpacity.Text = (_style.Stroke.Opacity * 100).ToString();
            TbStrokeWidth.Text = _style.StrokeThickness.ToString();
            CbStrokeEndStyle.SelectedIndex = (int)_style.StrokeEndLineCap;
            CbStrokeJoinStyle.SelectedIndex = (int)_style.StrokeLineJoin;
            RtStroke.Fill = _style.Stroke;

            if (UsesFill())
            {
                if (_style.Fill != null)
                {
                    RtFill.Fill = _style.Fill;
                    TbFillOpacity.Text = (_style.Fill.Opacity * 100).ToString();
                }
                else
                {
                    SolidColorBrush fill = new SolidColorBrush(Colors.Gray);
                    _style.Fill = fill;
                    RtFill.Fill = _style.Fill;
                    TbFillOpacity.Text = (_style.Fill.Opacity * 100).ToString();
                }
            }
        }

        //void SetRowVisibility(MapSourceTypes layerType)
        void SetRowVisibility(VectorSourceTypes vectorType)
        {
            MinimizeAllRows();

            if (vectorType == VectorSourceTypes.Point ||
                vectorType == VectorSourceTypes.MultiPoint)
            {
                RowPointStyle.Height = new GridLength(GRID_HEIGHT);
                RowPointWidth.Height = new GridLength(GRID_HEIGHT);
                RowPointHeight.Height = new GridLength(GRID_HEIGHT);
                RowPointCenter.Height = new GridLength(GRID_HEIGHT);
                RowFill.Height = new GridLength(GRID_HEIGHT);
                RowFillOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStroke.Height = new GridLength(GRID_HEIGHT);
                RowStrokeWidth.Height = new GridLength(GRID_HEIGHT);
                RowStrokeOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeStyle.Height = new GridLength(GRID_HEIGHT);
                RowEndStyle.Height = new GridLength(GRID_HEIGHT);
            }
            if (vectorType == VectorSourceTypes.LineString ||
                vectorType == VectorSourceTypes.MultiLineString)
            {
                RowStroke.Height = new GridLength(GRID_HEIGHT);
                RowStrokeWidth.Height = new GridLength(GRID_HEIGHT);
                RowStrokeOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeStyle.Height = new GridLength(GRID_HEIGHT);
                RowEndStyle.Height = new GridLength(GRID_HEIGHT);
                RowJoinStyle.Height = new GridLength(GRID_HEIGHT);
            }
            if (vectorType == VectorSourceTypes.Polygon ||
                vectorType == VectorSourceTypes.MultiPolygon)
            {
                RowFill.Height = new GridLength(GRID_HEIGHT);
                RowFillOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStroke.Height = new GridLength(GRID_HEIGHT);
                RowStrokeWidth.Height = new GridLength(GRID_HEIGHT);
                RowStrokeOpacity.Height = new GridLength(GRID_HEIGHT);
                RowStrokeStyle.Height = new GridLength(GRID_HEIGHT);
                RowEndStyle.Height = new GridLength(GRID_HEIGHT);
                RowJoinStyle.Height = new GridLength(GRID_HEIGHT);
            }

        }

        void MinimizeAllRows()
        {
            RowPointStyle.Height = new GridLength(0);
            RowPointWidth.Height = new GridLength(0);
            RowPointHeight.Height = new GridLength(0);
            RowPointCenter.Height = new GridLength(0);
            RowFill.Height = new GridLength(0);
            RowFillOpacity.Height = new GridLength(0);
            RowStroke.Height = new GridLength(0);
            RowStrokeWidth.Height = new GridLength(0);
            RowStrokeOpacity.Height = new GridLength(0);
            RowStrokeStyle.Height = new GridLength(0);
            RowEndStyle.Height = new GridLength(0);
            RowJoinStyle.Height = new GridLength(0);
        }

        Brush GetStrokeBrush()
        {
            return RtStroke.Fill;
        }

        Brush GetFillBrush()
        {
            return RtFill.Fill;
        }

        private void BtnPointStyle_Click(object sender, RoutedEventArgs e)
        {
            IconSelector iconSelector = new IconSelector();
            _dialogOpener.OpenDialog(iconSelector);
        }

        void SetPointWidth()
        {
            string inputStr = TbPointWidth.Text;
            if ( FormInputControl.CheckPositiveDouble(
                inputStr, IconErrorPointWidth)) {
                    _style.PointWidth = double.Parse(inputStr);
            }
        }

        void SetPointHeight()
        {
            string inputStr = TbPointHeight.Text;
            if ( FormInputControl.CheckPositiveDouble(
                inputStr, IconErrorPointHeight)) {
                    _style.PointHeight = double.Parse(inputStr);
            }
        }

        void SetPointCenterX()
        {
            string inputStr = TbPointCenterX.Text;
            if (FormInputControl.CheckPositiveDouble(inputStr, IconErrorPointCenter))
            {
                _style.AdjustX = double.Parse(inputStr);
            }
        }

        void SetPointCenterY()
        {
            string inputStr = TbPointCenterY.Text;
            if (FormInputControl.CheckPositiveDouble(inputStr, IconErrorPointCenter))
            {
                _style.AdjustY = double.Parse(inputStr);
            }
        }

        void SetFillOpacity()
        {
            string inputStr = TbFillOpacity.Text;
            if (FormInputControl.CheckNumberBetween(inputStr, IconErrorFillOpacity, 0,100))
            {
                _style.Fill.Opacity = double.Parse(inputStr) / 100;
            }
        }

        void SetStrokeWidth()
        {
            string inputStr = TbStrokeWidth.Text;
            if (FormInputControl.CheckPositiveDouble(inputStr, IconErrorStrokeWidth, true ))
            {
                _style.StrokeThickness = double.Parse(inputStr);
            }
        }

        void SetStrokeOpacity()
        {
            string inputStr = TbStrokeOpacity.Text;
            if (FormInputControl.CheckNumberBetween(inputStr, IconErrorStrokeOpacity,0,100))
            {
                _style.Stroke.Opacity = double.Parse(inputStr) / 100;
            }

        }

        void SetStrokeEndStyle()
        {
            int selectedIndex = CbStrokeEndStyle.SelectedIndex;
            PenLineCap lineCap = GetLineCapFromId(selectedIndex);
            _style.StrokeStartLineCap = lineCap;
            _style.StrokeEndLineCap = lineCap;
            _style.StrokeDashCap = lineCap;
        }

        void SetStrokeLineJoin()
        {
            int selectedIndex = CbStrokeJoinStyle.SelectedIndex;
            PenLineJoin lineJoin = GetLineJoinFromId(selectedIndex);
            _style.StrokeLineJoin = lineJoin;
        }

        bool UsesFill()
        {
            if (_vectorType == VectorSourceTypes.Point ||
                _vectorType == VectorSourceTypes.MultiPoint ||
                _vectorType == VectorSourceTypes.Polygon ||
                _vectorType == VectorSourceTypes.MultiPolygon)
            {
                return true;
            }
            else
            {
                return false;
            }
                
        }

        private void TbPointWidth_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointWidth();
        }

        private void TbPointHeight_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointHeight();
        }

        private void TbPointCenterX_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointCenterX();
        }

        private void TbPointCenterY_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetPointCenterY();
        }

        private void TbFillOpacity_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetFillOpacity();
        }

        private void TbStrokeWidth_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetStrokeWidth();
        }

        private void TbStrokeOpacity_LostFocus(object sender, RoutedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetStrokeOpacity();
        }

        private void CbStrokeStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }

        }

        private void CbStrokeEndStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
            SetStrokeEndStyle();
        }

        private void CbStrokeJoinStyle_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (!_inited)
            {
                return;
            }
        }

        private void BtnStroke_Click(object sender, RoutedEventArgs e)
        {
            BrushDialog colorDialog = new BrushDialog();
            if (RtStroke.Fill == null)
            {
                RtStroke.Fill = new SolidColorBrush(Colors.Gray);
                RtStroke.Fill.Opacity = 0.5;
            }
            colorDialog.SelectedFill = (SolidColorBrush)RtStroke.Fill;
            _dialogOpener.OpenDialog(colorDialog);
        }

        private void BtnFill_Click(object sender, RoutedEventArgs e)
        {
            BrushDialog colorDialog = new BrushDialog();
            if (RtFill.Fill == null)
            {
                RtFill.Fill = new SolidColorBrush(Colors.Gray);
                RtFill.Fill.Opacity = 0.5;
            }
            colorDialog.SelectedFill = (SolidColorBrush)RtFill.Fill;
            _dialogOpener.OpenDialog(colorDialog);
        }

        PenLineCap GetLineCapFromId(int id)
        {
            switch (id)
            {
                case (int)PenLineCap.Flat:
                    return PenLineCap.Flat;
                case (int)PenLineCap.Round:
                    return PenLineCap.Round;
                case (int)PenLineCap.Square:
                    return PenLineCap.Square;
                case (int)PenLineCap.Triangle:
                    return PenLineCap.Triangle;
                default:
                    return PenLineCap.Flat;
            }
        }

        PenLineJoin GetLineJoinFromId(int id)
        {
            switch (id)
            {
                case (int)PenLineJoin.Bevel:
                    return PenLineJoin.Bevel;
                case (int)PenLineJoin.Miter:
                    return PenLineJoin.Miter;
                case (int)PenLineJoin.Round:
                    return PenLineJoin.Round;
                default:
                    return PenLineJoin.Round;
            }
        }
	}
}